<template>
  <div class="form-container">
    <el-form
      ref="formRef"
      v-bind="$attrs"
      :model="formData"
      :rules="rules"
      :label-width="labelWidth"
      :label-position="labelPosition"
      :size="size"
      :disabled="disabled"
      @submit.prevent
    >
      <template v-for="(item, index) in formItems" :key="index">
        <!-- 栅格布局 -->
        <el-row v-if="item.type === 'row'" :gutter="item.gutter || 20">
          <el-col
            v-for="(col, colIndex) in item.cols"
            :key="colIndex"
            :span="col.span || 24"
            :offset="col.offset"
            :push="col.push"
            :pull="col.pull"
          >
            <el-form-item
              v-for="(formItem, formIndex) in col.items"
              :key="formIndex"
              v-bind="getFormItemProps(formItem)"
            >
              <!-- 表单项内容 -->
              <template v-if="formItem.slot">
                <slot :name="formItem.slot" :form="formData" />
              </template>
              
              <template v-else>
                <!-- 输入框 -->
                <el-input
                  v-if="formItem.type === 'input'"
                  v-model="formData[formItem.prop]"
                  v-bind="getComponentProps(formItem)"
                  @input="handleInput($event, formItem)"
                  @change="handleChange($event, formItem)"
                  @blur="handleBlur($event, formItem)"
                  @focus="handleFocus($event, formItem)"
                />
                
                <!-- 文本域 -->
                <el-input
                  v-else-if="formItem.type === 'textarea'"
                  v-model="formData[formItem.prop]"
                  type="textarea"
                  v-bind="getComponentProps(formItem)"
                  @input="handleInput($event, formItem)"
                  @change="handleChange($event, formItem)"
                  @blur="handleBlur($event, formItem)"
                  @focus="handleFocus($event, formItem)"
                />
                
                <!-- 数字输入框 -->
                <el-input-number
                  v-else-if="formItem.type === 'number'"
                  v-model="formData[formItem.prop]"
                  v-bind="getComponentProps(formItem)"
                  @change="handleChange($event, formItem)"
                  @blur="handleBlur($event, formItem)"
                  @focus="handleFocus($event, formItem)"
                />
                
                <!-- 选择器 -->
                <el-select
                  v-else-if="formItem.type === 'select'"
                  v-model="formData[formItem.prop]"
                  v-bind="getComponentProps(formItem)"
                  @change="handleChange($event, formItem)"
                  @blur="handleBlur($event, formItem)"
                  @focus="handleFocus($event, formItem)"
                >
                  <el-option
                    v-for="option in formItem.options"
                    :key="option.value"
                    :label="option.label"
                    :value="option.value"
                    :disabled="option.disabled"
                  />
                </el-select>
                
                <!-- 日期选择器 -->
                <el-date-picker
                  v-else-if="formItem.type === 'date'"
                  v-model="formData[formItem.prop]"
                  v-bind="getComponentProps(formItem)"
                  @change="handleChange($event, formItem)"
                  @blur="handleBlur($event, formItem)"
                  @focus="handleFocus($event, formItem)"
                />
                
                <!-- 日期范围选择器 -->
                <el-date-picker
                  v-else-if="formItem.type === 'daterange'"
                  v-model="formData[formItem.prop]"
                  type="daterange"
                  range-separator="至"
                  start-placeholder="开始日期"
                  end-placeholder="结束日期"
                  v-bind="getComponentProps(formItem)"
                  @change="handleChange($event, formItem)"
                  @blur="handleBlur($event, formItem)"
                  @focus="handleFocus($event, formItem)"
                />
                
                <!-- 时间选择器 -->
                <el-time-picker
                  v-else-if="formItem.type === 'time'"
                  v-model="formData[formItem.prop]"
                  v-bind="getComponentProps(formItem)"
                  @change="handleChange($event, formItem)"
                  @blur="handleBlur($event, formItem)"
                  @focus="handleFocus($event, formItem)"
                />
                
                <!-- 时间范围选择器 -->
                <el-time-picker
                  v-else-if="formItem.type === 'timerange'"
                  v-model="formData[formItem.prop]"
                  is-range
                  range-separator="至"
                  start-placeholder="开始时间"
                  end-placeholder="结束时间"
                  v-bind="getComponentProps(formItem)"
                  @change="handleChange($event, formItem)"
                  @blur="handleBlur($event, formItem)"
                  @focus="handleFocus($event, formItem)"
                />
                
                <!-- 开关 -->
                <el-switch
                  v-else-if="formItem.type === 'switch'"
                  v-model="formData[formItem.prop]"
                  v-bind="getComponentProps(formItem)"
                  @change="handleChange($event, formItem)"
                />
                
                <!-- 单选框组 -->
                <el-radio-group
                  v-else-if="formItem.type === 'radio'"
                  v-model="formData[formItem.prop]"
                  v-bind="getComponentProps(formItem)"
                  @change="handleChange($event, formItem)"
                >
                  <el-radio
                    v-for="option in formItem.options"
                    :key="option.value"
                    :label="option.value"
                    :disabled="option.disabled"
                  >
                    {{ option.label }}
                  </el-radio>
                </el-radio-group>
                
                <!-- 复选框组 -->
                <el-checkbox-group
                  v-else-if="formItem.type === 'checkbox'"
                  v-model="formData[formItem.prop]"
                  v-bind="getComponentProps(formItem)"
                  @change="handleChange($event, formItem)"
                >
                  <el-checkbox
                    v-for="option in formItem.options"
                    :key="option.value"
                    :label="option.value"
                    :disabled="option.disabled"
                  >
                    {{ option.label }}
                  </el-checkbox>
                </el-checkbox-group>
                
                <!-- 上传 -->
                <el-upload
                  v-else-if="formItem.type === 'upload'"
                  v-model:file-list="formData[formItem.prop]"
                  v-bind="getComponentProps(formItem)"
                  @change="handleChange($event, formItem)"
                  @success="handleSuccess($event, formItem)"
                  @error="handleError($event, formItem)"
                  @remove="handleRemove($event, formItem)"
                >
                  <template #trigger>
                    <el-button type="primary">点击上传</el-button>
                  </template>
                  <template #tip>
                    <div class="el-upload__tip">{{ formItem.tip }}</div>
                  </template>
                </el-upload>
                
                <!-- 富文本编辑器 -->
                <rich-editor
                  v-else-if="formItem.type === 'editor'"
                  v-model="formData[formItem.prop]"
                  v-bind="getComponentProps(formItem)"
                  @change="handleChange($event, formItem)"
                />
              </template>
            </el-form-item>
          </el-col>
        </el-row>
        
        <!-- 普通表单项 -->
        <el-form-item
          v-else
          v-bind="getFormItemProps(item)"
        >
          <!-- 表单项内容 -->
          <template v-if="item.slot">
            <slot :name="item.slot" :form="formData" />
          </template>
          
          <template v-else>
            <!-- 输入框 -->
            <el-input
              v-if="item.type === 'input'"
              v-model="formData[item.prop]"
              v-bind="getComponentProps(item)"
              @input="handleInput($event, item)"
              @change="handleChange($event, item)"
              @blur="handleBlur($event, item)"
              @focus="handleFocus($event, item)"
            />
            
            <!-- 文本域 -->
            <el-input
              v-else-if="item.type === 'textarea'"
              v-model="formData[item.prop]"
              type="textarea"
              v-bind="getComponentProps(item)"
              @input="handleInput($event, item)"
              @change="handleChange($event, item)"
              @blur="handleBlur($event, item)"
              @focus="handleFocus($event, item)"
            />
            
            <!-- 数字输入框 -->
            <el-input-number
              v-else-if="item.type === 'number'"
              v-model="formData[item.prop]"
              v-bind="getComponentProps(item)"
              @change="handleChange($event, item)"
              @blur="handleBlur($event, item)"
              @focus="handleFocus($event, item)"
            />
            
            <!-- 选择器 -->
            <el-select
              v-else-if="item.type === 'select'"
              v-model="formData[item.prop]"
              v-bind="getComponentProps(item)"
              @change="handleChange($event, item)"
              @blur="handleBlur($event, item)"
              @focus="handleFocus($event, item)"
            >
              <el-option
                v-for="option in item.options"
                :key="option.value"
                :label="option.label"
                :value="option.value"
                :disabled="option.disabled"
              />
            </el-select>
            
            <!-- 日期选择器 -->
            <el-date-picker
              v-else-if="item.type === 'date'"
              v-model="formData[item.prop]"
              v-bind="getComponentProps(item)"
              @change="handleChange($event, item)"
              @blur="handleBlur($event, item)"
              @focus="handleFocus($event, item)"
            />
            
            <!-- 日期范围选择器 -->
            <el-date-picker
              v-else-if="item.type === 'daterange'"
              v-model="formData[item.prop]"
              type="daterange"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              v-bind="getComponentProps(item)"
              @change="handleChange($event, item)"
              @blur="handleBlur($event, item)"
              @focus="handleFocus($event, item)"
            />
            
            <!-- 时间选择器 -->
            <el-time-picker
              v-else-if="item.type === 'time'"
              v-model="formData[item.prop]"
              v-bind="getComponentProps(item)"
              @change="handleChange($event, item)"
              @blur="handleBlur($event, item)"
              @focus="handleFocus($event, item)"
            />
            
            <!-- 时间范围选择器 -->
            <el-time-picker
              v-else-if="item.type === 'timerange'"
              v-model="formData[item.prop]"
              is-range
              range-separator="至"
              start-placeholder="开始时间"
              end-placeholder="结束时间"
              v-bind="getComponentProps(item)"
              @change="handleChange($event, item)"
              @blur="handleBlur($event, item)"
              @focus="handleFocus($event, item)"
            />
            
            <!-- 开关 -->
            <el-switch
              v-else-if="item.type === 'switch'"
              v-model="formData[item.prop]"
              v-bind="getComponentProps(item)"
              @change="handleChange($event, item)"
            />
            
            <!-- 单选框组 -->
            <el-radio-group
              v-else-if="item.type === 'radio'"
              v-model="formData[item.prop]"
              v-bind="getComponentProps(item)"
              @change="handleChange($event, item)"
            >
              <el-radio
                v-for="option in item.options"
                :key="option.value"
                :label="option.value"
                :disabled="option.disabled"
              >
                {{ option.label }}
              </el-radio>
            </el-radio-group>
            
            <!-- 复选框组 -->
            <el-checkbox-group
              v-else-if="item.type === 'checkbox'"
              v-model="formData[item.prop]"
              v-bind="getComponentProps(item)"
              @change="handleChange($event, item)"
            >
              <el-checkbox
                v-for="option in item.options"
                :key="option.value"
                :label="option.value"
                :disabled="option.disabled"
              >
                {{ option.label }}
              </el-checkbox>
            </el-checkbox-group>
            
            <!-- 上传 -->
            <el-upload
              v-else-if="item.type === 'upload'"
              v-model:file-list="formData[item.prop]"
              v-bind="getComponentProps(item)"
              @change="handleChange($event, item)"
              @success="handleSuccess($event, item)"
              @error="handleError($event, item)"
              @remove="handleRemove($event, item)"
            >
              <template #trigger>
                <el-button type="primary">点击上传</el-button>
              </template>
              <template #tip>
                <div class="el-upload__tip">{{ item.tip }}</div>
              </template>
            </el-upload>
            
            <!-- 富文本编辑器 -->
            <rich-editor
              v-else-if="item.type === 'editor'"
              v-model="formData[item.prop]"
              v-bind="getComponentProps(item)"
              @change="handleChange($event, item)"
            />
          </template>
        </el-form-item>
      </template>
      
      <!-- 表单操作按钮 -->
      <el-form-item v-if="showButtons" :class="buttonClass">
        <slot name="buttons">
          <el-button
            v-if="showSubmit"
            type="primary"
            :loading="loading"
            @click="handleSubmit"
          >
            {{ submitText }}
          </el-button>
          <el-button
            v-if="showReset"
            @click="handleReset"
          >
            {{ resetText }}
          </el-button>
        </slot>
      </el-form-item>
    </el-form>
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import RichEditor from '@/components/RichEditor/index.vue'

const props = defineProps({
  // 表单数据
  modelValue: {
    type: Object,
    required: true
  },
  // 表单项配置
  items: {
    type: Array,
    default: () => []
  },
  // 表单验证规则
  rules: {
    type: Object,
    default: () => ({})
  },
  // 标签宽度
  labelWidth: {
    type: [String, Number],
    default: '100px'
  },
  // 标签位置
  labelPosition: {
    type: String,
    default: 'right'
  },
  // 表单尺寸
  size: {
    type: String,
    default: 'default'
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false
  },
  // 是否显示按钮
  showButtons: {
    type: Boolean,
    default: true
  },
  // 是否显示提交按钮
  showSubmit: {
    type: Boolean,
    default: true
  },
  // 是否显示重置按钮
  showReset: {
    type: Boolean,
    default: true
  },
  // 提交按钮文字
  submitText: {
    type: String,
    default: '提交'
  },
  // 重置按钮文字
  resetText: {
    type: String,
    default: '重置'
  },
  // 按钮位置
  buttonPosition: {
    type: String,
    default: 'right'
  },
  // 加载状态
  loading: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits([
  'update:modelValue',
  'submit',
  'reset',
  'validate',
  'input',
  'change',
  'blur',
  'focus',
  'success',
  'error',
  'remove'
])

// 表单引用
const formRef = ref(null)

// 表单数据
const formData = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val)
})

// 表单项配置
const formItems = computed(() => props.items)

// 按钮样式
const buttonClass = computed(() => ({
  'form-buttons': true,
  [`form-buttons--${props.buttonPosition}`]: true
}))

// 获取表单项属性
const getFormItemProps = (item) => {
  const { type, prop, label, rules, ...rest } = item
  return {
    prop,
    label,
    rules: rules || props.rules[prop],
    ...rest
  }
}

// 获取组件属性
const getComponentProps = (item) => {
  const { type, prop, label, rules, options, slot, ...rest } = item
  return rest
}

// 处理输入
const handleInput = (value, item) => {
  emit('input', { value, item })
}

// 处理值变化
const handleChange = (value, item) => {
  emit('change', { value, item })
}

// 处理失焦
const handleBlur = (event, item) => {
  emit('blur', { event, item })
}

// 处理聚焦
const handleFocus = (event, item) => {
  emit('focus', { event, item })
}

// 处理上传成功
const handleSuccess = (response, item) => {
  emit('success', { response, item })
}

// 处理上传失败
const handleError = (error, item) => {
  emit('error', { error, item })
}

// 处理移除文件
const handleRemove = (file, item) => {
  emit('remove', { file, item })
}

// 处理提交
const handleSubmit = async () => {
  if (!formRef.value) return
  
  try {
    await formRef.value.validate()
    emit('submit', formData.value)
  } catch (error) {
    console.error('表单验证失败：', error)
  }
}

// 处理重置
const handleReset = () => {
  if (!formRef.value) return
  
  formRef.value.resetFields()
  emit('reset')
}

// 监听表单数据变化
watch(() => props.modelValue, (newVal) => {
  emit('validate')
}, { deep: true })

// 暴露方法
defineExpose({
  // 获取表单实例
  getForm: () => formRef.value,
  // 表单验证
  validate: () => formRef.value?.validate(),
  // 表单重置
  reset: handleReset,
  // 清空验证结果
  clearValidate: (props) => formRef.value?.clearValidate(props),
  // 滚动到指定字段
  scrollToField: (prop) => formRef.value?.scrollToField(prop)
})
</script>

<style lang="scss" scoped>
.form-container {
  .form-buttons {
    margin-top: 24px;
    
    &--left {
      text-align: left;
    }
    
    &--center {
      text-align: center;
    }
    
    &--right {
      text-align: right;
    }
  }
}
</style> 